package com.yh.csx.etl.config;

import java.io.File;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yh.csx.etl.util.FileUtils;
import com.yh.csx.etl.util.YamlUtils;

/**
 * @author Robin.Wang
 * @date 2020-03-20
 *
 */
public class EtlConfigMonitor {
    private static final Logger logger = LoggerFactory.getLogger(EtlConfigMonitor.class);

    private static final String ETL_NAME = "rdb";

    private String key;
    private FileAlterationMonitor fileMonitor;

    public void init(String key, EtlDataMappingManager etlMappingManager) {
        this.key = key;
        File confDir = FileUtils.getConfDirPath(ETL_NAME);
        try {
            FileAlterationObserver observer = new FileAlterationObserver(confDir,
                    FileFilterUtils.and(FileFilterUtils.fileFileFilter(), FileFilterUtils.suffixFileFilter("yml")));
            FileListener listener = new FileListener();
            observer.addListener(listener);
            fileMonitor = new FileAlterationMonitor(3000, observer);
            fileMonitor.start();

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    public void destroy() {
        try {
            fileMonitor.stop();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    private class FileListener extends FileAlterationListenerAdaptor {

        @Override
        public void onFileCreate(File file) {
            super.onFileCreate(file);
            try {
                // 加载新增的配置文件
                String configContent = EtlDataMappingManager.loadConfig(ETL_NAME + File.separator + file.getName());
                EtlDataMapping config = YamlUtils.load(configContent, EtlDataMapping.class);

                if (config == null) {
                    return;
                }
                // config.validate();
                if ((key == null && config.getOuterSourceKey() == null)
                        || (key != null && key.equals(config.getOuterSourceKey()))) {
                    // addConfigToCache(file, config);

                    logger.info("Add a new rdb mapping config: {} to canal adapter", file.getName());
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        @Override
        public void onFileChange(File file) {
            super.onFileChange(file);

            try {
                if (EtlDataMappingManager.MAPPINGS.containsKey(file.getName())) {
                    // 加载配置文件
                    String configContent = EtlDataMappingManager.loadConfig(ETL_NAME + File.separator + file.getName());
                    if (configContent == null) {
                        onFileDelete(file);
                        return;
                    }
                    EtlDataMapping config = YamlUtils.load(configContent, EtlDataMapping.class);
                    if (config == null) {
                        return;
                    }
                    // config.validate();
                    if ((key == null && config.getOuterSourceKey() == null)
                            || (key != null && key.equals(config.getOuterSourceKey()))) {
                        if (EtlDataMappingManager.MAPPINGS.containsKey(file.getName())) {
                            deleteConfigFromCache(file);
                        }
                        addConfigToCache(file, config);
                    } else {

                        throw new RuntimeException("Outer key not allowed modify");
                    }
                    logger.info("Change a rdb mapping config: {} of canal adapter", file.getName());
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        @Override
        public void onFileDelete(File file) {
            super.onFileDelete(file);

            try {
                if (EtlDataMappingManager.MAPPINGS.containsKey(file.getName())) {
                    deleteConfigFromCache(file);

                    logger.info("Delete a rdb mapping config: {} of canal adapter", file.getName());
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        private void addConfigToCache(File file, EtlDataMapping mappingConfig) {
            if (mappingConfig == null || mappingConfig.getDbMapping() == null) {
                return;
            }
            EtlDataMappingManager.MAPPINGS.put(file.getName(), mappingConfig);

        }

        private void deleteConfigFromCache(File file) {
            EtlDataMappingManager.MAPPINGS.remove(file.getName());
        }
    }
}
